#include "ch32x035.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "DevicesFlash.h"

/* 写入长度需要是 4 的整数倍 */
int8_t cFlashWriteDatas(uint32_t uiAddress, const void *pvBuff, int32_t iLength)
{
    uint32_t *puiDataAddress = (uint32_t *)pvBuff;
    int8_t cError = 0, cCnt = 0;

    if((iLength < 1) || ((uiAddress + iLength) > FLASH_USER_MAX_ADDR))
    {
        printf("cFlashWriteDatas uiAddress: %08X iLength: %d >= FLASH_USER_MAX_ADDR.\r\n", uiAddress, iLength);
        return 1;
    }

    /* unlock the flash program/erase controller */
    FLASH_Unlock();

    /* clear all pending flags */
    FLASH_ClearFlag(FLASH_FLAG_BSY);
    FLASH_ClearFlag(FLASH_FLAG_EOP);
    FLASH_ClearFlag(FLASH_FLAG_WRPRTERR);
    FLASH_ClearFlag(FLASH_FLAG_OPTERR);

    /* 每次写入2字节 */
    while(iLength > 0)
    {
        /* erase the flash pages */
        if((uiAddress & (FLASH_PAGE_SIZE - 1)) == 0)
        {
            cCnt = 8;
            /* erase flash */
            while((FLASH_ErasePage(uiAddress) != FLASH_COMPLETE) & (--cCnt));

            /* clear all pending flags */
            FLASH_ClearFlag(FLASH_FLAG_BSY);
            FLASH_ClearFlag(FLASH_FLAG_EOP);
            FLASH_ClearFlag(FLASH_FLAG_WRPRTERR);
            FLASH_ClearFlag(FLASH_FLAG_OPTERR);

            if(cCnt == 0)
            {
                printf("cFlashWriteDatas FLASH_ErasePage addr: 0x%08X error.\r\n", uiAddress);
                cError |= 2;
                break;
            }
        }

        /* program flash */
        if(*(volatile uint32_t *)uiAddress != *puiDataAddress)
        {
            FLASH_BufLoad(uiAddress, *puiDataAddress);
        }

        /* clear all pending flags */
        FLASH_ClearFlag(FLASH_FLAG_BSY);
        FLASH_ClearFlag(FLASH_FLAG_EOP);
        FLASH_ClearFlag(FLASH_FLAG_WRPRTERR);
        FLASH_ClearFlag(FLASH_FLAG_OPTERR);

        ++puiDataAddress;
        uiAddress += 4;
        iLength -= 4;
    }

    /* lock the main FMC after the program operation */
    FLASH_Lock();

    return cError;
}

int8_t cFlashReadDatas(uint32_t uiAddress, void *pvBuff, int32_t iLength)
{
    if((iLength < 1) || ((uiAddress + iLength) > FLASH_USER_MAX_ADDR))
    {
        printf("cFlashReadDatas uiAddress: %08X iLength: %d >= FLASH_USER_MAX_ADDR.\r\n", uiAddress, iLength);
        return 1;
    }

    /* Read Flash */
    memcpy(pvBuff, (uint8_t *)uiAddress, iLength);

    return 0;
}
